Spring Cloud Config 笔记补充

作者: 李多多 日期: 2020-08-14
Spring Cloud
Spring Cloud Config 笔记补充

@[TOC](Spring Cloud Config)

1. 基本用法

1.1 简介

Spring Ccloud Config 是一个分布式系统配置管理的解决方案,它包含了 Client 和 Server 。配置文件放在 Server 端,通过接口的形式提供给 Client。

主要功能

  • 集中管理各个微服务/环境的配置文件(中央仓库 统一打包 发快递)
  • 支持多种开发语言和高并发查询
  • 提供server(服务端)和客户端(client)
  • 配置文件一经修改 可快速生效 但是client立刻生效需要中间件
  • 配置文件通过git/svn进行管理(支持版本回退)

1.2 准备工作-提交文件

在本地找一个位置,新建目录 client1 添加 3 个文件.properties结尾,上传到git上。 一个文件夹代表一个微服务。

在这里插入图片描述

1.3 ConfigServer搭建

首先创建一个 ConfigServer 工程,添加如下依赖:

在这里插入图片描述
完事后启动添加注解:

@SpringBootApplication
@EnableConfigServer // 启动ConfigServer
public class ConfigServerApplication {

public static void main(String[] args) {
SpringApplication.run(ConfigServerApplication.class, args);
}

}

修改配置文件:

spring.application.name=config-server
server.port=8081

# 配置文件仓库地址
spring.cloud.config.server.git.uri=https://github.com/xxx/configRepo.git

# 仓库中, 配置文件的目录
spring.cloud.config.server.git.search-paths=client1

spring.cloud.config.server.git.username=xxxx@163.com
spring.cloud.config.server.git.password=

然后启动 ConfigServer 项目,就可以访问配置文件了,访问地址: http://localhost:8081/client1/prod/main (github上面master分支现在已经没有了)

接下来修改本地配置文件并重新提交到 GitHub ,此时,刷新 ConfigServer 接口,就可以及时看到更改的内容。

访问规则

  • /{application}/{profile}[/{label}] /{application}-{profile}.yml
  • /{label}/{application}-{profile}.yml
  • /{application}-{profile}.properties
  • /{label}/{application}-{profile}.properties

{application} 就是应用名称,对应到配置文件上来,就是配置文件的名称部分,例如我上面创建的配置文件。
{profile} 就是配置文件的版本,我们的项目有开发版本、测试环境版本、生产环境版本,对应到配置文件上来就是以 application-{profile}.yml 加以区分,例如application-dev.yml、application-sit.yml、application-prod.yml。
{label} 表示 git 分支,默认是 master 分支,如果项目是以分支做区分也是可以的,那就可以通过不同的 label 来控制访问不同的配置文件了。

1.4 ConfigClient搭建

首先创建一个 Spring Boot 项目,添加如下依赖:

在这里插入图片描述

项目创建成功后,在 Resoures 目录下,添加 boostrap.properties 配置(boostrap.properties 优先级高于 application.properties),内容如下:

# 下面三行配置,分别对应 config-server 中的 {application}、{profile}以及{label}占位符
spring.application.name=client1
spring.cloud.config.profile=dev
spring.cloud.config.label=main
spring.cloud.config.uri=http://localhost:8081
server.port=8082

接下来创建一个HelloController 测试:

@RestController
public class HelloController {
@Value("${javaboy}")
String javaboys;
@GetMapping("/hello")
public String hello(){
return javaboys;
}
}

访问:http://localhost:8082/hello

1.5 配置

使用占位符灵活控制查询目录。
修改 config-server 配置文件:

spring.cloud.config.server.git.search-paths={application}

这里的 {application} 占位符,表示链接上来的 client1 的 spring.application.name 属性的值。
在 config-server 中,也可以用 {profile} 表示 client 的 spring.cloud.config.profile,也可以用 {label} 表示 client 的 spring.cloud.config.label
虽然在实际开发中,配置文件一般都是放在 Git 仓库,但是 config-server 也支持将配置文件放在 classpath 下。
在 config-server 中添加如下配置:

# 表示让 config-server 从 classpath 下查找配置,而不是去 Git 仓库中查找
spring.profiles.active=native

也可以在 config-server 中,添加如下配置,表示指定配置文件的位置:

spring.cloud.config.server.native.search-locations=file:/E:/properties/

2. 配置文件加解密

2.1 常见加密方案

  • 不可逆加密
  • 可逆加密

不可逆加密

理论上无法根据已加密的密文推导出明文(常用算法 MD5消息摘要算法 SHA安全散列算法) ,一般用在密码加密上。

可逆加密

对称加密:加密和解密密钥是一样的(算法 aes 3des des)。

非对称加密:加密的密钥和解密的密钥不同。加密的称为公钥,可以给任何人; 解密的叫私钥(只有自己知道)。 常见算法RSA

2.2 对称加密

首先下载不限长度的JCE:oracle中下载
将下载的文件解压,解压出来的 jar 拷贝到 Java 安装目录中: E:**\lib\security
然后,在 config-server 的 bootstrap.properties 配置文件中,添加如下内容配置密钥:

# 密钥
encrypt.key=javaboy

然后启动 config-server 访问如下地址,查看密钥配置是否OK:
在这里插入图片描述
在这里插入图片描述
然后在 postman 访问:http://localhost:8081/encrypt ,这是一个 post 请求,访问该地址,可以对一段明文进行加密。把加密后的明文存储到Git仓库中,存储时,要加一个 {cipher} 前:
在这里插入图片描述
修改本地文件如下,并提交至github 上去。
在这里插入图片描述
然后访问: http://localhost:8081/client1/dev/main 查看效果,如下:
在这里插入图片描述
config-client 需要重启才会感知并生效(后续考虑用中间件等办法解决)。config-client 重启后访问如下:
在这里插入图片描述

2.3 非对称加密

首先生成一个密钥对:
在命令行执行如下命令,生成 keystore :

keytool -genkeypair -alias config-server -keyalg RSA -keystore F:\BaiduNetdiskDownload\config-server.keystore

命令执行完后,拷贝生成的 keystore 文件到 config-server 的 resources 目录下。
然后在 config-server 的 bootstrap.properties 目录中,添加如下配置:

encrypt.key-store.location=config-server.keystore
encrypt.key-store.alias=config-server
encrypt.key-store.password=111111
encrypt.key-store.secret=111111

在pom.xml 的 build 节点上,添加如下配置,防止 keystore 文件被过滤。

<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.keystore</include>
</includes>
</resource>
</resources>

然后重启 config-server ,测试方法与对称加密一致。
在这里插入图片描述
接下来加密文件 ,并cv 到github 上进行测试。
在这里插入图片描述
重启/启动 config-server和 config-client ,访问如下:

在这里插入图片描述

在这里插入图片描述

3. 安全管理

防止用户直接通过访问 config-server 看到配置文件内容,我们可以用 spring security 来保护 config-server 接口。
首先在 config-server 中添加 spring security 依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

添加完依赖后,config-server 中的接口就被保护起来了。
默认生成的密码不好记,所以我们可以在 config-server 中配置自己的密码。
在 config-server 的配置文件中,添加如下配置,固定用户名密码:

spring.security.user.name=user
spring.security.user.password=321

然后在 config-client 的 bootstrap.properties 配置文件中,添加如下配置:

spring.cloud.config.username=user
spring.cloud.config.password=321

重 config-server和 config-client ,访问如下即成功:

在这里插入图片描述

4. 服务化

首先启动 Eureka 。
然后让 config-server 和 config-client 都注册到 Eureka。给他两添加如下依赖:

<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>

然后在两个 application.properties 配置文件中配置注册信息。

eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

接下来修改 config-client 配置文件,不再直接写死 config-server 地址。如下:

# 下面三行配置,分别对应 config-server 中的 {application}、{profile}以及{label}占位符
spring.application.name=client1
spring.cloud.config.profile=test
spring.cloud.config.label=main
#spring.cloud.config.uri=http://localhost:8081

# 开启通过 eureka 获取 config-server 的功能
spring.cloud.config.discovery.enabled=true
# 配置 config-server 服务名称
spring.cloud.config.discovery.service-id=config-server
server.port=8082

spring.cloud.config.username=user
spring.cloud.config.password=321

# 注册 eureka
eureka.client.serviceUrl.defaultZone=http://localhost:1111/eureka/

加入 eureka client 之后,启动 config-server 可能会报错。此时我们重新生成一个 jks 格式的密钥。cmd命令框:

keytool -genkeypair -alias new-config-server -keyalg RSA -keypass 123456 -keystore D:\git\config-server.jks -storepass 123456

生成之后,将文件拷贝到 configserver 的 resources 目录下,同时修改 bootstrap.properties 配置。

# 密钥 【对称加密】
#encrypt.key=javaboy

encrypt.key-store.location=classpath:config-server.jks
encrypt.key-store.alias=mytestkey
encrypt.key-store.password=111111
encrypt.key-store.secret=111111

spring.security.user.name=user
spring.security.user.password=321

同时修改 pom 文件:

		<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.jks</include>
<!-- <include>**/*.keystore</include>-->
</includes>
</resource>
</resources>

为了得到效果 非对称加密那部分就不用了。修改 config-client 配置文件:

config-client profile: test

重启后访问成功如下:
在这里插入图片描述

5. 动态刷新(config-client感知数据更新)

当配置文件发生变化后,config-server 可以及时感知到变化,但是 config-client 不会及时感知到变化,默认情况下, config-client 只有重启才会加载到最新的配置文件(实际上这个在后面可以结合消息中间件来做,这里为了简单先这样做)。
首先给 config-client 添加如下依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

然后,添加配置,使 refresh 端点暴露出来:

management.endpoints.web.exposure.include=refresh

最后,再给 config-client 使用了配置文件的地方加上 @RefreshScope 注解,这样当配置改变后,只需要调用 refresh 端点,config-client 中的配置就可以自动刷新。

@RestController
@RefreshScope
public class HelloController {
@Value("${javaboy}")
String javaboys;
@GetMapping("/hello")
public String hello(){
return javaboys;
}
}

接下来修改本地的配置文件并提交至 GitHub,内容如下(将test改为test123):
在这里插入图片描述
提交成功后,这个时候你如果不做其他操作的话,直接访问config-client ,实际上那个文件是不会变的。至此,以后只要配置文件发生变化,发送 post 请求,调用 http://localhost:8082/actuator/refresh 接口即可,配置文件就会自动刷新。
在这里插入图片描述
调用成后再去访问 config-client 接口,发现已经改变,如下:
在这里插入图片描述

6. 请求失败重试

config-client 在调用 config-server 时,一样也可能发生请求失败的问题,这个时候我们可以配置一个请求重试的功能。
要给 config-client 添加重试功能,只需要添加如下依赖:

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.retry</groupId>
<artifactId>spring-retry</artifactId>
</dependency>

然后,修改配置,开启失败快速响应(默认情况下,config-client 访问 config-server 时,如果它访问失败了,这个时候项目还是会继续启动,不会马上报错。而快速相应在这里访问失败会立马报错,进行重试)。

# 开启失败快速响应
spring.cloud.config.fail-fast=true

然后,注释掉配置文件的用户名和密码,重启 config-client ,此时加载配置文件失败,就会自动重试。

再次启动如下图:
在这里插入图片描述
也可以通过如下配置保证服务的可用性:

# 开启失败快速响应
spring.cloud.config.fail-fast=true
# 请求重试的初始间隔时间
spring.cloud.config.retry.initial-interval=1000
# 最大重试次数
spring.cloud.config.retry.max-attempts=6
# 重试时间间隔乘数
spring.cloud.config.retry.multiplier=1.1
# 最大间隔时间
spring.cloud.config.retry.max-interval=2000

地址https://github.com/astronger/springcloud-simple-samples